/******************************************************************************************************
Copyright (C) 2019 Mestrelab Research S.L. All rights reserved.

This file is part of the MNova scripting toolkit.

Authorized users of MNova Software may use this file freely, but this file is provided AS IS
with NO WARRANTY OF ANY KIND, INCLUDING THE WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE.
*****************************************************************************************************/

/*globals NMRSpectrum, Molecule, Peaks, Multiplets, NMRAssignments, File, Dir, NMReDATAImporter, print,
serialization, Document, MolecularAssignmentsParser, Atom, SpectrumRegion, Multiplet, JList, NMRProcessing,
TextStream, Str, Application, mainWindow, FileDialog, AssignmentReporter, FileInfo, Peak, UnZip, NMReDATACommon*/
/*jslint plusplus: true, indent: 4*/

/** Default constructor of the converter
 * Defines the file filter
*/
function NMReDATAImporter(aPath) {
	"use strict";

	var fileInfo = new FileInfo(aPath);

	if (fileInfo.isDir) {
		this.tempDir = new Dir(aPath);
	} else {
		if (File.exists(aPath)) {
			if (aPath.endsWith(".zip")) {
				this.tempDir = new Dir(this.unzipFile(aPath));
			}
		}
	}
	this.moleculeIds = [];
	this.assignmentParsers = {};
	this.spectraTags = {};
}


NMReDATAImporter.prototype.importNMReDATA = function () {
	"use strict";

	var i, sdfFiles;

	this.doc = mainWindow.newDocument();
	sdfFiles = this.detectSDFs();

	if (sdfFiles) {
		this.correctTempdir(sdfFiles);
		this.openSDFs(sdfFiles);
		this.chooseNMReDATA();
		this.loadNMReDATAImporters();
		this.detectSpectraTags();

		for (i = 0; i < this.moleculeIds.length; i++) {
			this.processNMReDATA(this.moleculeIds[i]);
		}
		this.doc.update();
		return true;
	}
};


NMReDATAImporter.prototype.correctTempdir = function (sdfFiles) {
	"use strict";

	var path = File.absDirPath(sdfFiles[0]);
	this.tempDir = new Dir(path);
};


NMReDATAImporter.prototype.processNMReDATA = function (aMoleculeId) {
	"use strict";

	this.importAssignmentTag(aMoleculeId);
	this.assignmentParsers[aMoleculeId].correctProtonAssignments();
	this.importJcouplingTag(aMoleculeId);
	this.importSpectraTags(aMoleculeId);
	this.assignmentParsers[aMoleculeId].cleanAssignments();
	print(JSON.stringify(this.assignmentParsers[aMoleculeId].assignments, false, 4));
	this.assignmentParsers[aMoleculeId].loadAssignmentsInMolecule();
	this.updateSpectra();
};


NMReDATAImporter.prototype.importSpectraTags = function (aMoleculeId) {
	"use strict";

	var tagName;

	for (tagName in this.spectraTags) {
		if (this.spectraTags.hasOwnProperty(tagName)) {
			this.importSpectrumTag(tagName, aMoleculeId);
		}
	}
};


NMReDATAImporter.prototype.importSpectrumTag = function (aTagName, aMoleculeId) {
	"use strict";

	var i, tagText, mol, line, aLineArray, spectra, spectrum, correlationType = "",
		lines = [];

	mol = new Molecule(this.doc.getItem(aMoleculeId));
	tagText = mol.getSDFData(aTagName);
	serialization.history = false;

	if (tagText) {
		lines = tagText.trim().split("\n");
	}

	for (i = 0; i < lines.length; i++) {
		line = lines[i].replace("\\", "");
		if (!this.ignoreLine(line)) {
			if (line.startsWith("CorType") || line.startsWith("CorrType")) {
				correlationType = line.split("=")[1];
			} else if (line.startsWith("Spectrum_Location")) {
				if (!this.spectraTags[aTagName].id) {
					aLineArray = line.split("=");
					if (this.openSpectrumFile(aLineArray[1].trim(), aTagName)) {
						spectra = this.doc.itemsByName("NMR Spectrum");
						spectrum = spectra[spectra.length - 1];
						this.applyProcessingTemplate(aTagName, spectrum);
						mol.linkItems("Assignments", spectrum);
						this.spectraTags[aTagName].id = spectrum.uuid;
					} else {
						break;
					}
				} else {
					spectrum = this.doc.getItem(this.spectraTags[aTagName].id);
					mol.linkItems("Assignments", spectrum);
				}
			} else {
				this.parseSpectrumLine(line, aTagName, aMoleculeId, correlationType);
			}
		}
	}
	serialization.history = true;
};


NMReDATAImporter.prototype.updateSpectra = function () {
	"use strict";

	var i, spectra;

	spectra = this.doc.itemsByName("NMR Spectrum");
	for (i = 0; i < spectra.length; i++) {
		spectra[i].update();
	}
	this.doc.update();
};


NMReDATAImporter.prototype.ignoreLine = function (line) {
	"use strict";

	if (line.startsWith(";")) {
		return true;
	}
	if (line.startsWith("Pulseprogram")) {
		return true;
	}
	if (line.startsWith("Larmor")) {
		return true;
	}
	if (line.startsWith("MD5")) {
		return true;
	}
	if (line.startsWith("Decoupled")) {
		return true;
	}
	if (line.startsWith("Nondecoupled")) {
		return true;
	}
	if (line.startsWith("Jcamp_location")) {
		return true;
	}
	if (line.startsWith("zip_file_Location") || line.startsWith("Zip_file_Location")) {
		return true;
	}
};


NMReDATAImporter.prototype.openSpectrumFile = function (aPath, aTagName) {
	"use strict";

	var correctPath, nDim;

	nDim = parseInt(aTagName.split("_")[1], 10);

	if (aPath.startsWith("file:./")) {
		aPath = aPath.slice(7, aPath.length);
		correctPath = this.tempDir.filePath(aPath);
		if (File.exists(correctPath)) {
			if (serialization.open(correctPath)) {
				return true;
			}
		}
	}
	if (aPath.endsWith("pdata/1") || aPath.endsWith("pdata/1/")) {
		aPath += (nDim === 1 ? "/1r" : "/2rr");
		correctPath = this.tempDir.filePath(aPath);
		if (File.exists(correctPath)) {
			if (serialization.open(correctPath)) {
				return true;
			}
		}
	}
};


NMReDATAImporter.prototype.applyProcessingTemplate = function (aTagName, aSpectrum) {
	"use strict";

	var path, correctPath, proc, spectrum;

	spectrum = new NMRSpectrum(aSpectrum);
	if (this.mnovaProcTemplates && this.mnovaProcTemplates[aTagName]) {
		path = this.mnovaProcTemplates[aTagName];
		if (path.startsWith("file:./")) {
			path = path.slice(7, path.length);
			correctPath = this.tempDir.filePath(path);
			if (File.exists(correctPath)) {
				proc = new NMRProcessing(correctPath);
				spectrum.process(proc);
			}
		}
	}
};


NMReDATAImporter.prototype.parseSpectrumLine = function (aLine, aTagName, aMoleculeId, correlationType) {
	"use strict";

	var lineValues;

	if (this.spectraTags[aTagName].type === "1D") {
		lineValues = this.parse1DLine(aLine);
		this.import1DInfo(lineValues, aTagName, aMoleculeId);
	}
	if (this.spectraTags[aTagName].type === "2D") {
		lineValues = this.parse2DLine(aLine);
		this.import2DInfo(lineValues, aTagName, aMoleculeId, correlationType);
	}
};


NMReDATAImporter.prototype.import2DInfo = function (aInfo, aTagName, aMoleculeId, correlationType) {
	"use strict";

	var spectrum, currentPeaks, aPeak, f1, f2, assignmentF1, assignmentF2;

	spectrum = new NMRSpectrum(this.doc.getItem(this.spectraTags[aTagName].id));

	assignmentF1 = this.assignmentParsers[aMoleculeId].getFromAtomLabelNMReDATA(aInfo.f1);
	assignmentF2 = this.assignmentParsers[aMoleculeId].getFromAtomLabelNMReDATA(aInfo.f2);

	if (assignmentF1 && assignmentF1.length && assignmentF2 && assignmentF2.length) {
		f1 = assignmentF1[0].shift[0].shift;
		f2 = assignmentF2[0].shift[0].shift;
		currentPeaks =  new Peaks(spectrum.peaks());
		aPeak = new Peak(f1, f2, spectrum);
		this.assignmentParsers[aMoleculeId].linkPeakToLabelNMReDATA(aPeak, aInfo.f1);
		this.assignmentParsers[aMoleculeId].linkPeakToLabelNMReDATA(aPeak, aInfo.f2);
		this.assignmentParsers[aMoleculeId].addCorrelationFromNMReDATA(aInfo.f1, aInfo.f2, correlationType);
		currentPeaks.append(aPeak);
		spectrum.setPeaks(currentPeaks);
	}

	spectrum.update();
	this.doc.update();
};


NMReDATAImporter.prototype.import1DInfo = function (aInfo, aTagName, aMoleculeId) {
	"use strict";

	var currentMultiplets, aMultiplet, multipletShiftIsCorrect, multipletShiftNotChecked, overlappedWithMultiplet,
		isMultipletAssigned, aMultipletIndex, candidateMultiplet,
		spectrum = new NMRSpectrum(this.doc.getItem(this.spectraTags[aTagName].id));

	if (!aInfo.S) {
		aInfo.S = "s";
		aInfo.J = "";
	}

	currentMultiplets = spectrum.multiplets();
	aMultiplet = this.createMultiplet(aInfo, spectrum);

	if (aMultiplet.isValid()) {
		if (aInfo.shift.delta || aInfo.shift.delta === 0) {
			multipletShiftIsCorrect = (Math.abs(aMultiplet.delta - aInfo.shift.delta) < 0.0001);
		} else {
			multipletShiftNotChecked = true;
		}

		if (multipletShiftIsCorrect || multipletShiftNotChecked) {
			if (aInfo.L) {
				aMultiplet = this.addMultipletAssignmentAndLabel(aMultiplet, aInfo.L, aMoleculeId);
				aMultiplet = this.setMultiplicityFromSDF(aMultiplet, aInfo);
				currentMultiplets.append(aMultiplet);
				spectrum.setMultiplets(currentMultiplets);
			} else {
				overlappedWithMultiplet = this.isMultipletOverlapped(aMultiplet, currentMultiplets);
				if (!overlappedWithMultiplet) {
					aMultiplet = this.setMultiplicityFromSDF(aMultiplet, aInfo);
					currentMultiplets.append(aMultiplet);
					spectrum.setMultiplets(currentMultiplets);
				}
			}
		}
	} else {
		aMultipletIndex = this.getMultipletFromRegion(currentMultiplets, aInfo);
		if (typeof aMultipletIndex === "number") {
			candidateMultiplet = currentMultiplets.at(aMultipletIndex);
			isMultipletAssigned = this.detectIfMultipletIsAssigned(candidateMultiplet, aMoleculeId);
			if (!isMultipletAssigned && aInfo.L) {
				candidateMultiplet = this.addMultipletAssignmentAndLabel(candidateMultiplet, aInfo.L, aMoleculeId);
				spectrum.setMultiplets(currentMultiplets);
			}
		}
	}

	spectrum.update();
	this.doc.update();
};


NMReDATAImporter.prototype.createMultiplet = function (aInfo, spectrum) {
	"use strict";

	var multipletRange, aRegion, rangeFrom, rangeTo, aMultiplet;

	if (aInfo.S === "m" || (aInfo.shift.rangeFrom && aInfo.shift.rangeTo)) {
		aRegion = new SpectrumRegion(aInfo.shift.rangeFrom, aInfo.shift.rangeTo);
	} else {
		try {
			multipletRange = this.calculateMultipletPpmRange(aInfo.S, aInfo.J, spectrum.frequency());
		} catch (err) {}
		if (multipletRange) {
			rangeFrom = aInfo.shift.delta - multipletRange / 2;
			rangeTo = aInfo.shift.delta + multipletRange / 2;
			aRegion = new SpectrumRegion(rangeFrom, rangeTo);
		}
	}

	if (aRegion) {
		aMultiplet = new Multiplet(spectrum, aRegion);
	}
	return aMultiplet;
};


NMReDATAImporter.prototype.addMultipletAssignmentAndLabel = function (aMultiplet, aLabels, aMoleculeId) {
	"use strict";

	var i, j, assignmentsFromLabel,
		multipletLabels = [],
		assignments = [],
		assignmentLabels = aLabels.split(",");

	for (i = 0; i < assignmentLabels.length; i++) {
		assignmentsFromLabel = this.assignmentParsers[aMoleculeId].getFromAtomLabelNMReDATA(assignmentLabels[i]);
		assignments = assignments.concat(assignmentsFromLabel);
		if (assignmentsFromLabel && assignmentsFromLabel.length) {
			multipletLabels.push(assignmentsFromLabel[0].atom.label);
			for (j = 0; j < assignmentsFromLabel.length; j++) {
				this.assignmentParsers[aMoleculeId].linkMultipletToAtomAssignment(aMultiplet, assignmentsFromLabel[j]);
			}
		}
	}
	aMultiplet.name = multipletLabels.join(",");

	return aMultiplet;
};


NMReDATAImporter.prototype.setMultiplicityFromSDF = function (aMultiplet, aInfo) {
	"use strict";

	var i, newJList,
		jsArray = aInfo.J.split(",");

	if (aMultiplet.category !== aInfo.S) {
		aMultiplet.category = aInfo.S;
	}
	if (aInfo.S === "m") {
		newJList = new JList();
	} else {
		newJList = new JList();
		for (i = 0; i < jsArray.length; i++) {
			newJList.append(parseFloat(jsArray[i]));
		}
	}
	if (aInfo.S !== "s") {
		aMultiplet.setJList(newJList);
	}

	return aMultiplet;
};


NMReDATAImporter.prototype.calculateMultipletPpmRange = function (aMultiplicity, aJs, aFrequency) {
	"use strict";

	var i, aJ,
		smallHzRange = 4,
		hzRange = 6,
		maxJ = 0,
		splittings = aMultiplicity.split(""),
		jsArray = aJs.split(",");

	if (aMultiplicity === "s") {
		return smallHzRange / aFrequency;
	}

	for (i = 0; i < jsArray.length; i++) {
		maxJ = Math.max(maxJ, parseFloat(jsArray[i]));
	}

	hzRange = 6.0;
	if (splittings.length === jsArray.length) {
		for (i = 0; i < splittings.length; i++) {
			aJ = parseFloat(jsArray[i]);
			hzRange += NMReDATACommon.splittingToSegments(splittings[i]) * aJ;
		}
	} else {
		for (i = 0; i < splittings.length; i++) {
			hzRange += NMReDATACommon.splittingToSegments(splittings[i]) * maxJ;
		}
	}

	return hzRange / aFrequency;
};


NMReDATAImporter.prototype.isMultipletOverlapped = function (aMultiplet, currentMultiplets) {
	"use strict";

	var i, aCurrentMultiplet;

	for (i = 0; i < currentMultiplets.count; i++) {
		aCurrentMultiplet = currentMultiplets.at(i);
		if (aCurrentMultiplet.delta > aMultiplet.delta) {
			if (aMultiplet.rangeMax > aCurrentMultiplet.rangeMin) {
				return true;
			}
		} else if (aCurrentMultiplet.delta < aMultiplet.delta) {
			if (aMultiplet.rangeMin < aCurrentMultiplet.rangeMax) {
				return true;
			}
		} else {
			return aCurrentMultiplet;
		}
	}
};


NMReDATAImporter.prototype.detectIfMultipletIsAssigned = function (aMultiplet, aMoleculeId) {
	"use strict";

	var i, aCurrentMoleculeId, aAssignment;

	for (i = 0; i < this.moleculeIds.length; i++) {
		aCurrentMoleculeId = this.moleculeIds[i];
		if (aCurrentMoleculeId === aMoleculeId) {
			return false;
		}
		aAssignment = this.assignmentParsers[aMoleculeId].getFromShiftUUID(aMultiplet.uuid);
		if (aAssignment && aAssignment.length) {
			return true;
		}
	}
};


NMReDATAImporter.prototype.getMultipletFromRegion = function (currentMultiplets, aInfo) {
	"use strict";

	var i, aCurrentMultiplet;

	for (i = 0; i < currentMultiplets.count; i++) {
		aCurrentMultiplet = currentMultiplets.at(i);
		if (aCurrentMultiplet.rangeMax === aInfo.rangeTo && aCurrentMultiplet.rangeMin === aInfo.rangeFrom) {
			return i;
		}
	}
};


NMReDATAImporter.prototype.parse1DLine = function (aLine) {
	"use strict";

	var i, subArray, aLineArray, lineArrayLength, shift, shift1, shift2,
		parsed = {};

	aLineArray = aLine.split(";")[0].split(",");

	shift = aLineArray[0].trim().split("-");
	parsed.shift = {};
	if (shift.length === 1) {
		parsed.shift.delta = parseFloat(shift);
	} else {
		shift1 = parseFloat(shift[0]);
		shift2 = parseFloat(shift[1]);
		if (shift1 > shift2) {
			parsed.shift.rangeFrom = shift2;
			parsed.shift.rangeTo = shift1;
		} else {
			parsed.shift.rangeFrom = shift1;
			parsed.shift.rangeTo = shift2;
		}
	}

	lineArrayLength = aLineArray.length;
	for (i = 1; i < lineArrayLength; i++) {
		if (aLineArray[i] && aLineArray[i].indexOf("=") === -1) {
			aLineArray[i - 1] += "," + aLineArray[i].trim();
			aLineArray.splice(i, 1);
			i--;
		}
	}

	for (i = 1; i < aLineArray.length; i++) {
		subArray = aLineArray[i].trim().split("=");
		parsed[subArray[0]] = subArray[1];
	}
	return parsed;
};


NMReDATAImporter.prototype.parse2DLine = function (aLine) {
	"use strict";

	var i, fs, subArray, aLineArray, lineArrayLength,
		parsed = {};

	aLineArray = aLine.split(";")[0].split(",");
	fs = aLineArray[0].trim().split("/");
	parsed.f1 = fs[0];
	parsed.f2 = fs[1];

	lineArrayLength = aLineArray.length;
	for (i = 1; i < lineArrayLength; i++) {
		if (aLineArray[i] && aLineArray[i].indexOf("=") === -1) {
			aLineArray[i - 1] += "," + aLineArray[i];
			aLineArray.splice(i, 1);
			i--;
		}
	}

	for (i = 1; i < aLineArray.length; i++) {
		subArray = aLineArray[i].trim().split("=");
		parsed[subArray[0]] = subArray[1];
	}
	return parsed;
};


NMReDATAImporter.prototype.detectSpectraTags = function () {
	"use strict";

	var i, j, tags, tagName, mol, tagText, lines, line, splittedLine,
		ref1D = "NMREDATA_1D",
		ref2D = "NMREDATA_2D";

	mol = new Molecule(this.doc.getItem(this.moleculeIds[0]));

	tags = mol.sdfNames();
	for (i = 0; i < tags.length; i++) {
		tagName = tags[i];
		if (tagName.startsWith(ref1D)) {
			this.spectraTags[tagName] = {"type" : "1D", "id": undefined};
		}
		if (tagName.startsWith(ref2D)) {
			this.spectraTags[tagName] = {"type" : "2D", "id": undefined};
		}
		if (tagName === "MNOVA_PROC_TEMPLATES") {
			this.mnovaProcTemplates = {};
			tagText = mol.getSDFData(tagName);
			lines = tagText.split("\n");
			for (j = 0; j < lines.length; j++) {
				line = lines[j].replace("\\", "");
				splittedLine = line.split("=");
				this.mnovaProcTemplates[splittedLine[0]] = splittedLine[1];
			}
		}
	}
};


NMReDATAImporter.prototype.importJcouplingTag = function (aMoleculeId) {
	"use strict";

	var i, jCouplingsText, line, lines, mol,
		tagName = "NMREDATA_J";

	mol = new Molecule(this.doc.getItem(aMoleculeId));
	jCouplingsText = mol.getSDFData(tagName);
	if (jCouplingsText) {
		lines = jCouplingsText.trim().split("\n");
		for (i = 0; i < lines.length; i++) {
			line = lines[i].replace("\\", "");
			this.parseJLineToAssignments(line, aMoleculeId);
		}
	}
};


NMReDATAImporter.prototype.parseJLineToAssignments = function (aLine, aMoleculeId) {
	"use strict";

	var aLineArray, label1, label2, aJValue;

	aLineArray = aLine.split(",");

	if (aLineArray.length > 2) {
		label1 = aLineArray[0].trim();
		label2 = aLineArray[1].trim();
		aJValue = parseFloat(aLineArray[2].trim());
		this.assignmentParsers[aMoleculeId].addJCouplingFromNMReDATA(label1, label2, aJValue);
	}
};


NMReDATAImporter.prototype.importAssignmentTag = function (aMoleculeId) {
	"use strict";

	var i, assignmentText, mol, line, lines,
		aNMRAssignments = [],
		tagName = "NMREDATA_ASSIGNMENT";

	mol = new Molecule(this.doc.getItem(aMoleculeId));
	assignmentText = mol.getSDFData(tagName);
	if (assignmentText) {
		lines = assignmentText.trim().split("\n");
		for (i = 0; i < lines.length; i++) {
			line = lines[i].replace("\\", "");
			aNMRAssignments.push(this.lineToAtomAssignment(line, aMoleculeId));
		}
		this.assignmentParsers[aMoleculeId].assignments = aNMRAssignments;
	}
};


NMReDATAImporter.prototype.lineToAtomAssignment = function (aLine, aMoleculeId) {
	"use strict";

	var i, mol, aLineArray, atomInfo, labelInfo, totalShifts,
		shifts = [],
		aNMRAtomAssignment = {"atom" : {}, "couplings" : {}, "correlations" : {}, "shift" : []};

	mol = new Molecule(this.doc.getItem(aMoleculeId));
	aLineArray = aLine.split(",");

	totalShifts = aLineArray.length - 2;
	for (i = 0; i < totalShifts; i++) {
		shifts.push(this.textToShiftsArray(aLineArray[1 + i].trim()));
	}
	atomInfo = this.textToAtomInfo(aLineArray[aLineArray.length - 1].trim());
	labelInfo = this.textToLabelInfo(aLineArray[0].trim(), atomInfo, aMoleculeId);

	aNMRAtomAssignment.atom.indexNMReDATA = aLineArray[2].trim();
	aNMRAtomAssignment.atom.labelNMReDATA = aLineArray[0].trim();
	aNMRAtomAssignment.atom.number = labelInfo.number;
	aNMRAtomAssignment.atom.index = atomInfo.index;
	if (labelInfo.protonNotation) {
		mol.atom(atomInfo.index).protonNotation = atomInfo.element.protonNotation;
		aNMRAtomAssignment.atom.protonNotation = labelInfo.protonNotation;
	}
	aNMRAtomAssignment.atom.explicit = (!atomInfo.element);
	if (atomInfo.element) {
		aNMRAtomAssignment.element = atomInfo.element;
	} else {
		aNMRAtomAssignment.element = mol.atom(atomInfo.index).elementSymbol;
	}

	for (i = 0; i < shifts.length; i++) {
		if (shifts[i].length === 1) {
			aNMRAtomAssignment.shift.push({"shift" : parseFloat(shifts[i][0]), idTypes : []});
		}
	}
	if (labelInfo.h) {
		aNMRAtomAssignment.atom.h = labelInfo.h;
	}
	if (labelInfo.protonNotation) {
		mol.atom(atomInfo.index).protonNotation = labelInfo.protonNotation;
	}
	aNMRAtomAssignment.atom.label = this.assignmentParsers[aMoleculeId].getAtomLabel(aNMRAtomAssignment);

	return aNMRAtomAssignment;
};


NMReDATAImporter.prototype.loadNMReDATAImporters = function () {
	"use strict";

	var i, molId, molecule;

	for (i = 0; i < this.moleculeIds.length; i++) {
		molId = this.moleculeIds[i];
		molecule = new Molecule(this.doc.getItem(molId));
		this.assignmentParsers[molId] = new MolecularAssignmentsParser(molecule);
	}
};


NMReDATAImporter.prototype.detectSDFs = function () {
	"use strict";

	var i, allFiles,
		sdfFiles = [];

	allFiles = NMReDATACommon.getDirContents(this.tempDir.absPath, []);
	serialization.history = false;

	for (i = 0; i < allFiles.length; i++) {
		if (allFiles[i].indexOf(".sdf") !== -1 || allFiles[i].indexOf(".SDF") !== -1) {
			sdfFiles.push(allFiles[i]);
		}
	}
	return sdfFiles;
};


NMReDATAImporter.prototype.openSDFs = function (sdfFiles) {
	"use strict";

	serialization.history = false;
	serialization.open(sdfFiles);
	serialization.history = true;
};


NMReDATAImporter.prototype.chooseNMReDATA = function () {
	"use strict";

	var i, j, mol, tagName, tags, molecules, isValid,
		versionTagName = "NMREDATA_VERSION";

	molecules = this.doc.itemsByName("Molecule");
	for (i = 0; i < molecules.length; i++) {
		isValid = false;
		mol = new Molecule(molecules[i]);
		if (mol.isValid()) {
			tags = mol.sdfNames();
			for (j = 0; j < tags.length; j++) {
				tagName = tags[j];
				if (tagName === versionTagName) {
					this.moleculeIds.push(mol.uuid);
					isValid = true;
					break;
				}
			}
		}
		if (!isValid) {
			Document.deleteItems(mol);
		}
	}
};


NMReDATAImporter.prototype.unzipFile = function (aFile) {
	"use strict";

	var d, outputDir, unzip,
		fileInfo = new FileInfo(aFile),
		outPath = "";

	d = fileInfo.dir;
	outputDir = "%1_unzipped".arg(fileInfo.baseName);
	d.mkdir(outputDir);

	outPath = d.filePath(outputDir);
	unzip = new UnZip(aFile);
	if (unzip.open() === 0) {
		unzip.extract(outPath);
		unzip.close();
	}
	return outPath + "/" + fileInfo.baseName;
};


NMReDATAImporter.prototype.textToShiftsArray = function (aText) {
	'use strict';

	var shiftsArray = [];

	aText = aText.replace(" ", "");
	shiftsArray = aText.split("-");

	return shiftsArray;
};


NMReDATAImporter.prototype.textToAtomInfo = function (aText) {
	'use strict';

	var index, element,
		atom = {};

	index = aText.match(/\d+/g);
	if (index && index.length === 1) {
		index = index[0];
		atom.index = parseInt(index, 10);
	} else {
		return undefined;
	}

	element = aText.replace(/\d/g, "");
	if (element) {
		atom.element = element;
	}

	return atom;
};


NMReDATAImporter.prototype.textToLabelInfo = function (aText, aInfo, aMoleculeId) {
	'use strict';

	var number, atom, hLabel, numberStart, numberLength, notationInfo, mol,
		aAssignment = {};

	if (aInfo.element === "H") {
		aAssignment.implicit = true;
	}

	mol = new Molecule(this.doc.getItem(aMoleculeId));

	atom = mol.atom(aInfo.index);
	number = atom.number;
	aAssignment.number = number;

	numberStart = aText.indexOf(number);
	numberLength = number.length;
	hLabel = aText.slice(numberStart + numberLength);

	notationInfo = this.toProtonNotation(hLabel);
	if (notationInfo.protonNotation) {
		aAssignment.protonNotation = notationInfo.protonNotation;
	}
	if (notationInfo.h) {
		aAssignment.h = notationInfo.h;
	}

	return aAssignment;
};


NMReDATAImporter.prototype.toProtonNotation = function (aCurrentNotation) {
	'use strict';

	var i, aFoundIndex,
		atomNotations = [Atom.QUOTES, Atom.AB, Atom.ALPHABETA, Atom.CISTRANS, Atom.AXEQ],
		hIndexs = [ [],
					["'",   "a", "alpha", "cis",   "ax"],
					["''",  "b", "beta",  "trans", "eq"],
					["'''", "c"] ],
		notationInfo = {"protonNotation" : undefined, "hIndex" : undefined};

	for (i = 0; i < hIndexs.length; i++) {
		aFoundIndex = hIndexs[i].indexOf(aCurrentNotation);
		if (aFoundIndex !== -1) {
			notationInfo.h = hIndexs[i][1];
			if (i === 1 || i === 2) {
				notationInfo.protonNotation = atomNotations[aFoundIndex];
			}
		}
	}
	return notationInfo;
};


